home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / mpeg_play-2.1 / 24bit.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  14KB  |  553 lines

  1. /*
  2.  * 24bit.c --
  3.  *
  4.  *      This file implements conversions from images to 24 bit color.
  5.  *
  6.  */
  7.  
  8. /*
  9.  * Copyright (c) 1995 The Regents of the University of California.
  10.  * All rights reserved.
  11.  * 
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose, without fee, and without written agreement is
  14.  * hereby granted, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  * 
  17.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  18.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  19.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  20.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  21.  * 
  22.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  23.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  25.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  26.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  27.  */
  28.  
  29. #include "video.h"
  30. #include "dither.h"
  31. #include "proto.h"
  32.  
  33. BOOLEAN rgb = TRUE;
  34.  
  35. /*
  36.  *    R = L + 1.366*Cr;
  37.  *    G = L - 0.700*Cb - 0.334*Cr;
  38.  *    B = L + 1.732*Cb;
  39.  *
  40.  * We'll use fixed point by adding two extra bits after the decimal.
  41.  * We also don't bother doing the -.002*Cb for R or the -.006*Cr for B because
  42.  * they create a difference of at most 1, virtually indistinguishable
  43.  */
  44.  
  45. #define BITS    8
  46. #define ONE     ((int) 1)
  47. #define CONST_SCALE    (ONE << BITS)
  48. #define ROUND_FACTOR    (ONE << (BITS-1))
  49.  
  50. /* Macro to convert integer to fixed. */
  51. #define UP(x)    (((int)(x)) << BITS)
  52.  
  53. /* Macro to convert fixed to integer (with rounding). */
  54. #define DOWN(x)    (((x) + ROUND_FACTOR) >> BITS)
  55.  
  56. /* Macro to convert a float to a fixed */
  57. #define FIX(x)  ((int) ((x)*CONST_SCALE + 0.5))
  58. #define CLAMP(ll,x,ul)    ( ((x)<(ll)) ?(ll):( ((x)>(ul)) ?(ul):(x)))
  59. /* Those above arent too fast, here is a user-supplied alternative: */
  60. #define UP_255 UP(255)
  61. #define DO_ASSIGN(row,C1,C2,C3)                                       \
  62.          if ((unsigned) C1 < (unsigned) UP_255 &&                     \
  63.              (unsigned) C2 < (unsigned) UP_255 &&                     \
  64.              (unsigned) C3 < (unsigned) UP_255)                       \
  65.            /* Fast common case (no overflow). */                      \
  66.            *row++ = (C1 >> BITS) + (C2 & 0xff00) + ((C3 & 0xff00) <<BITS);\
  67.          else {                                                       \
  68.            /* Overflow in C3, C2 or C1. */                            \
  69.           v = 0;                                                      \
  70.             if (C1 >= 0)                                              \
  71.              if (C1 > UP_255)                                         \
  72.                v = 255;                                               \
  73.              else                                                     \
  74.                  v = C1 >> BITS;                                      \
  75.            if (C2 >= 0)                                               \
  76.              if (C2 > UP_255)                                         \
  77.                v += 255 << BITS;                                      \
  78.              else                                                     \
  79.                  v += C2 & 0xff00;                                    \
  80.            if (C3 >= 0)                                               \
  81.              if (C3 > UP_255)                                         \
  82.                v += 255 << (BITS + BITS);                             \
  83.              else                                                     \
  84.                  v += (C3 & 0xff00) << BITS;                          \
  85.            *row++ = v;}        
  86. /* This is dumb, but a little faster than anything else I've thought up */
  87. #define GET_ASSIGN_VAL(C1,C2,C3)                                      \
  88.   if ((unsigned) C1 < (unsigned) UP_255 &&                            \
  89.       (unsigned) C2 < (unsigned) UP_255 &&                            \
  90.              (unsigned) C3 < (unsigned) UP_255)                       \
  91.   /* Fast common case (no overflow). */                               \
  92.   v = (C1 >> BITS) + (C2 & 0xff00) + ((C3 & 0xff00) <<BITS);          \
  93.   else {  /* Overflow in C3, C2 or C1. */                             \
  94.     v = 0;                                                            \
  95.     if (C1 >= 0)                                                      \
  96.        if (C1 > UP_255)                                               \
  97.      v = 255;                                                     \
  98.        else                                                           \
  99.      v = C1 >> BITS;                                              \
  100.     if (C2 >= 0)                                                      \
  101.        if (C2 > UP_255)                                               \
  102.      v += 255 << BITS;                                            \
  103.        else                                                           \
  104.      v += C2 & 0xff00;                                            \
  105.     if (C3 >= 0)                                                      \
  106.        if (C3 > UP_255)                                               \
  107.      v += 255 << (BITS + BITS);                                   \
  108.        else                                                           \
  109.      v += (C3 & 0xff00) << BITS;                                  \
  110.      }        
  111.  
  112. static int *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
  113.  
  114. /*
  115.  *--------------------------------------------------------------
  116.  *
  117.  * InitColorDither --
  118.  *
  119.  *    To get rid of the multiply and other conversions in color
  120.  *    dither, we use a lookup table.
  121.  *
  122.  * Results:
  123.  *    None.
  124.  *
  125.  * Side effects:
  126.  *    The lookup tables are initialized.
  127.  *
  128.  *    R = L + 1.366*Cr;
  129.  *    G = L - 0.700*Cb - 0.334*Cr;
  130.  *    B = L + 1.732*Cb;
  131.  * 
  132.  *    Equations streamlined due to imperceptable difference in output.
  133.  *
  134.  * We'll use fixed point by adding two extra bits after the decimal.
  135.  *
  136.  *--------------------------------------------------------------
  137.  */
  138.  
  139. void
  140.   InitColorDither()
  141. {
  142.   int CR, CB, i;
  143.  
  144.   Cb_b_tab = (int *)malloc(256*sizeof(int));
  145.   Cr_g_tab = (int *)malloc(256*sizeof(int));
  146.   Cb_g_tab = (int *)malloc(256*sizeof(int));
  147.   Cr_r_tab = (int *)malloc(256*sizeof(int));
  148.  
  149.   for (i=0; i<256; i++) {
  150.     CB = CR = i;
  151.  
  152.     CB -= 128; CR -= 128;
  153.  
  154.     Cr_r_tab[i] = FIX(1.366) * CR;
  155.     Cr_g_tab[i] = -FIX(0.700) * CR;
  156.     Cb_g_tab[i] = -FIX(0.334) * CB;   
  157.  
  158.     Cb_b_tab[i] = FIX(1.732) * CB;
  159.   }
  160. }
  161.  
  162.  
  163. /*
  164.  *--------------------------------------------------------------
  165.  *
  166.  * ColorDitherImage --
  167.  *
  168.  *    Converts image into 24 bit color.
  169.  *
  170.  * Results:
  171.  *    None.
  172.  *
  173.  * Side effects:
  174.  *    None.
  175.  *
  176.  *--------------------------------------------------------------
  177.  */
  178.  
  179. void
  180.   ColorDitherImage(lum, cr, cb, out, rows, cols)
  181. unsigned char *lum;
  182. unsigned char *cr;
  183. unsigned char *cb;
  184. unsigned char *out;
  185. int cols, rows;
  186.  
  187. {
  188.   int L, CR, CB;
  189.   unsigned int *row1, *row2;
  190.   unsigned char *lum2;
  191.   int x, y;
  192.   int cr_r, cr_g, cb_g, cb_b;
  193.   int R, G, B;
  194.   unsigned int v;        /* used in DO_ASSIGN */
  195.  
  196.   row1 = (unsigned int *)out;
  197.   row2 = row1 + cols;
  198.   lum2 = lum + cols;
  199.  
  200.   /* Code in these two halves of the if should be identical except for the DO_ASSIGN */
  201.   if (!rgb) {
  202.     for (y=0;  y<rows;  y+=2) {
  203.       for (x=0;  x<cols;  x+=2) {
  204.     CR = *cr++; 
  205.     CB = *cb++;
  206.     cr_r = Cr_r_tab[CR];
  207.     cr_g = Cr_g_tab[CR];
  208.     cb_g = Cb_g_tab[CB];
  209.     cb_b = Cb_b_tab[CB];
  210.         
  211.     L = *lum++;
  212.     L = UP(L);
  213.     R = L + cr_r;
  214.     G = L + cr_g + cb_g;
  215.     B = L + cb_b;
  216. if (R<0 || G<0 || B<0) {
  217.   printf("%d %d %d\n", R, G, B);
  218. }
  219.     DO_ASSIGN(row1,R,G,B);
  220.  
  221.     if (x != cols - 1) {
  222.       CR = (CR + *cr) >> 1;
  223.       CB = (CB + *cb) >> 1;
  224.       cr_r = Cr_r_tab[CR];
  225.       cr_g = Cr_g_tab[CR];
  226.       cb_g = Cb_g_tab[CB];
  227.       cb_b = Cb_b_tab[CB];
  228.     }
  229.  
  230.     L = *lum++;
  231.     L = UP(L);
  232.     R = L + cr_r;
  233.     G = L + cr_g + cb_g;
  234.     B = L + cb_b;
  235.     DO_ASSIGN(row1,R,G,B);
  236.  
  237.     /*
  238.      * Now, do second row.
  239.      */
  240.  
  241.     if (y != rows - 1) {
  242.       CR = (CR + *(cr - 1 + cols/2)) >> 1;
  243.       CB = (CB + *(cb - 1 + cols/2)) >> 1;
  244.       cr_r = Cr_r_tab[CR];
  245.       cr_g = Cr_g_tab[CR];
  246.       cb_g = Cb_g_tab[CB];
  247.       cb_b = Cb_b_tab[CB];
  248.     }
  249.  
  250.     L = *lum2++;
  251.     L = UP(L);
  252.     R = L + cr_r;
  253.     G = L + cr_g + cb_g;
  254.     B = L + cb_b;
  255.     DO_ASSIGN(row2,R,G,B);
  256.  
  257.     L = *lum2++;
  258.     L = UP(L);
  259.     R = L + cr_r;
  260.     G = L + cr_g + cb_g;
  261.     B = L + cb_b;
  262.     DO_ASSIGN(row2,R,G,B);
  263.       }
  264.       lum += cols;
  265.       lum2 += cols;
  266.       row1 += cols;
  267.       row2 += cols;
  268.     }
  269.   } else {
  270.     for (y=0;  y<rows;  y+=2) {
  271.       for (x=0;  x<cols;  x+=2) {
  272.     CR = *cr++; 
  273.     CB = *cb++;
  274.     cr_r = Cr_r_tab[CR];
  275.     cr_g = Cr_g_tab[CR];
  276.     cb_g = Cb_g_tab[CB];
  277.     cb_b = Cb_b_tab[CB];
  278.  
  279.     L = *lum++;
  280.     L = UP(L);
  281.     R = L + cr_r;
  282.     G = L + cr_g + cb_g;
  283.     B = L + cb_b;
  284.     DO_ASSIGN(row1,B,G,R);
  285.  
  286.     if (x != cols - 1) {
  287.       CR = (CR + *cr) >> 1;
  288.       CB = (CB + *cb) >> 1;
  289.       cr_r = Cr_r_tab[CR];
  290.       cr_g = Cr_g_tab[CR];
  291.       cb_g = Cb_g_tab[CB];
  292.       cb_b = Cb_b_tab[CB];
  293.     }
  294.  
  295.     L = *lum++;
  296.     L = UP(L);
  297.     R = L + cr_r;
  298.     G = L + cr_g + cb_g;
  299.     B = L + cb_b;
  300.     DO_ASSIGN(row1,B,G,R);
  301.     /*
  302.      * Now, do second row.
  303.      */
  304.  
  305.     if (y != rows - 1) {
  306.       CR = (CR + *(cr - 1 + cols/2)) >> 1;
  307.       CB = (CB + *(cb - 1 + cols/2)) >> 1;
  308.       cr_r = Cr_r_tab[CR];
  309.       cr_g = Cr_g_tab[CR];
  310.       cb_g = Cb_g_tab[CB];
  311.       cb_b = Cb_b_tab[CB];
  312.     }
  313.  
  314.     L = *lum2++;
  315.     L = UP(L);
  316.     R = L + cr_r;
  317.     G = L + cr_g + cb_g;
  318.     B = L + cb_b;
  319.     DO_ASSIGN(row2,B,G,R);
  320.  
  321.     L = *lum2++;
  322.     L = UP(L);
  323.     R = L + cr_r;
  324.     G = L + cr_g + cb_g;
  325.     B = L + cb_b;
  326.     DO_ASSIGN(row2,B,G,R);
  327.       }
  328.       lum += cols;
  329.       lum2 += cols;
  330.       row1 += cols;
  331.       row2 += cols;
  332.     }
  333.   }
  334.   
  335. }
  336.  
  337.  
  338.  
  339.  
  340. /*
  341.  *--------------------------------------------------------------
  342.  *
  343.  * Color2DitherImage --
  344.  *
  345.  *    Converts image into 24 bit color.
  346.  *
  347.  * Results:
  348.  *    None.
  349.  *
  350.  * Side effects:
  351.  *    None.
  352.  *
  353.  *--------------------------------------------------------------
  354.  */
  355.  
  356. void
  357.   Color2DitherImage(lum, cr, cb, out, rows, cols)
  358. unsigned char *lum;
  359. unsigned char *cr;
  360. unsigned char *cb;
  361. unsigned char *out;
  362. int cols, rows;
  363.  
  364. {
  365.   int L, CR, CB;
  366.   unsigned int *row1, *row2;
  367.   unsigned char *lum2;
  368.   int x, y;
  369.   unsigned int v        /* set in DO_ASSIGN */;
  370.   int cr_r;
  371.   int cr_g;
  372.   int cb_g;
  373.   int cb_b;
  374.   
  375.   /* In this version row1 and row2 each point to 2 rows. */
  376.   /* Also, each row is twice as long. */
  377.   row1 = (unsigned int *)out;
  378.   row2 = row1 + cols*4;
  379.   lum2 = lum + cols;
  380.  
  381.   /* the following code should be the same in each branch, except for 
  382.    * GET_ASSIGN_VAL */
  383.   if (!rgb) {
  384.     for (y = 0;  y < rows;  y += 2) {
  385.       for (x = 0;  x < cols;  x += 2) {
  386.     int R, G, B;
  387.       
  388.     CR = *cr++;
  389.     CB = *cb++;
  390.     cr_r = Cr_r_tab[CR];
  391.     cr_g = Cr_g_tab[CR];
  392.     cb_g = Cb_g_tab[CB];
  393.     cb_b = Cb_b_tab[CB];
  394.       
  395.     L = *lum++;
  396.     L = UP(L);
  397.     R = L + cr_r;
  398.     G = L + cr_g + cb_g;
  399.     B = L + cb_b;
  400.     GET_ASSIGN_VAL(R,G,B);
  401.     *row1 = v;        /* v set in GET_ASSIGN_VAL */
  402.     *(row1+1) = v;
  403.     *(row1+cols*2) = v;
  404.     *(row1+cols*2+1) = v;
  405.     row1+=2;
  406.       
  407.     if (x != cols - 2) {
  408.       CR = (CR + *cr) >> 1;
  409.       CB = (CB + *cb) >> 1;
  410.       cr_r = Cr_r_tab[CR];
  411.       cr_g = Cr_g_tab[CR];
  412.       cb_g = Cb_g_tab[CB];
  413.       cb_b = Cb_b_tab[CB];
  414.     }
  415.     L = *lum++;
  416.     L = UP(L);
  417.     R = L + cr_r;
  418.     G = L + cr_g + cb_g;
  419.     B = L + cb_b;
  420.     GET_ASSIGN_VAL(R,G,B);
  421.     *row1 = v;
  422.     *(row1+1) = v;
  423.     *(row1+cols*2) = v;
  424.     *(row1+cols*2+1) = v;
  425.     row1+=2;
  426.       
  427.     /*
  428.      * Now, do second row.
  429.      */
  430.     if (y != rows - 2) {
  431.       CR = (CR + *(cr - 1 + cols/2)) >> 1;
  432.       CB = (CB + *(cb - 1 + cols/2)) >> 1;
  433.       cr_r = Cr_r_tab[CR];
  434.       cr_g = Cr_g_tab[CR];
  435.       cb_g = Cb_g_tab[CB];
  436.       cb_b = Cb_b_tab[CB];
  437.     }
  438.     L = *lum2++;
  439.     L = UP(L);
  440.     R = L + cr_r;
  441.     G = L + cr_g + cb_g;
  442.     B = L + cb_b;
  443.     GET_ASSIGN_VAL(R,G,B);
  444.     *row2 = v;
  445.     *(row2+1) = v;
  446.     *(row2+cols*2) = v;
  447.     *(row2+cols*2+1) = v;
  448.     row2+=2;
  449.       
  450.     L = *lum2++;
  451.     L = UP(L);
  452.     R = L + cr_r;
  453.     G = L + cr_g + cb_g;
  454.     B = L + cb_b;
  455.     GET_ASSIGN_VAL(R,G,B);
  456.     *row2 = v;
  457.     *(row2+1) = v;
  458.     *(row2+cols*2) = v;
  459.     *(row2+cols*2+1) = v;
  460.     row2+=2;
  461.       }
  462.       lum += cols;
  463.       lum2 += cols;
  464.       row1 += cols*6;
  465.       row2 += cols*6;
  466.     }
  467.   } else {
  468.     for (y=0; y<rows; y+=2) {
  469.       for (x=0; x<cols; x+=2) {
  470.     int R, G, B;
  471.       
  472.     CR = *cr++;
  473.     CB = *cb++;
  474.     cr_r = Cr_r_tab[CR];
  475.     cr_g = Cr_g_tab[CR];
  476.     cb_g = Cb_g_tab[CB];
  477.     cb_b = Cb_b_tab[CB];
  478.  
  479.     L = *lum++;
  480.     L = UP(L);
  481.     R = L + cr_r;
  482.     G = L + cr_g + cb_g;
  483.     B = L + cb_b;
  484.     GET_ASSIGN_VAL(B,G,R);
  485.     *row1 = v;        /* v set in GET_ASSIGN_VAL */
  486.     *(row1+1) = v;
  487.     *(row1+cols*2) = v;
  488.     *(row1+cols*2+1) = v;
  489.     row1+=2;
  490.  
  491.     if (x != cols - 2) {
  492.       CR = (CR + *cr) >> 1;
  493.       CB = (CB + *cb) >> 1;
  494.       cr_r = Cr_r_tab[CR];
  495.       cr_g = Cr_g_tab[CR];
  496.       cb_g = Cb_g_tab[CB];
  497.       cb_b = Cb_b_tab[CB];
  498.     }
  499.     L = *lum++;
  500.     L = UP(L);
  501.     R = L + cr_r;
  502.     G = L + cr_g + cb_g;
  503.     B = L + cb_b;
  504.     GET_ASSIGN_VAL(B,G,R);
  505.     *row1 = v;
  506.     *(row1+1) = v;
  507.     *(row1+cols*2) = v;
  508.     *(row1+cols*2+1) = v;
  509.     row1+=2;
  510.       
  511.     /*
  512.      * Now, do second row.
  513.      */
  514.     if (y != rows - 2) {
  515.       CR = (CR + *(cr - 1 + cols/2)) >> 1;
  516.       CB = (CB + *(cb - 1 + cols/2)) >> 1;
  517.       cr_r = Cr_r_tab[CR];
  518.       cr_g = Cr_g_tab[CR];
  519.       cb_g = Cb_g_tab[CB];
  520.       cb_b = Cb_b_tab[CB];
  521.     }
  522.     L = *lum2++;
  523.     L = UP(L);
  524.     R = L + cr_r;
  525.     G = L + cr_g + cb_g;
  526.     B = L + cb_b;
  527.     GET_ASSIGN_VAL(B,G,R);
  528.     *row2 = v;
  529.     *(row2+1) = v;
  530.     *(row2+cols*2) = v;
  531.     *(row2+cols*2+1) = v;
  532.     row2+=2;
  533.       
  534.     L = *lum2++;
  535.     L = UP(L);
  536.     R = L + cr_r;
  537.     G = L + cr_g + cb_g;
  538.     B = L + cb_b;
  539.     GET_ASSIGN_VAL(B,G,R);
  540.     *row2 = v;
  541.     *(row2+1) = v;
  542.     *(row2+cols*2) = v;
  543.     *(row2+cols*2+1) = v;
  544.     row2+=2;
  545.       }
  546.       lum += cols;
  547.       lum2 += cols;
  548.       row1 += cols*6;
  549.       row2 += cols*6;
  550.     }
  551.   }
  552. }
  553.